package com.bucg.cjcloud.gb28181.sip;

import com.bucg.cjcloud.gb28181.sip.support.BranchManager;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sip.Dialog;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.Header;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class MessageHandel {
    @Autowired
    private SipServerInfo sipinfo;
    @Autowired
    private AddressFactory addressFactory;
    @Autowired
    private MessageFactory messageFactory;
    @Autowired
    private HeaderFactory headerFactory;
    @Resource(name = "fromAddress")
    private Address address;
    @Resource(name = "contactHeader")
    private ContactHeader contactHeader;
    @Autowired
    private SipProvider sipProvider;
    @Autowired
    private BranchManager branchManager;

    /***
     * 获取新的from,new tag
     *
     * @throws ParseException
     */
    public FromHeader getFromHeader() throws ParseException {
        return headerFactory.createFromHeader(address, RandomStringUtils.randomNumeric(5));

    }

    public static Map<String, String> callIdMap = new HashMap<>();
    public static Map<String, Dialog> diaLogMap = new HashMap<>();

    /**
     * 获取 ToHeader
     *
     * @throws ParseException
     */
    public ToHeader getToHeader(String username, String address, String tag) throws ParseException {
        SipURI toAddress = addressFactory.createSipURI(username, address);
        Address toNameAddress = addressFactory.createAddress(toAddress);
        toNameAddress.setDisplayName(username);
        return headerFactory.createToHeader(toNameAddress, tag);
    }

    public void sendMessage(String toAddress, String toUsername, String message)
            throws ParseException, InvalidArgumentException, SipException {
        CallIdHeader callIdHeader = sipProvider.getNewCallId();
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader =
                headerFactory.createViaHeader(sipinfo.getIp(), sipinfo.getPort(), "udp", "branch1");
        viaHeaders.add(viaHeader);
        ContentTypeHeader contentTypeHeader =
                headerFactory.createContentTypeHeader("Application", "MANSCDP+xml");
        sendMessage(toAddress, toUsername, message, Request.MESSAGE, callIdHeader, viaHeaders,
                contentTypeHeader, new ArrayList<>(0), null);
    }

    public void sendMessageINVITE(String toAddress, String toUsername, String message,
                                  List<Header> headers) throws ParseException, InvalidArgumentException, SipException {
        CallIdHeader callIdHeader = sipProvider.getNewCallId();
        callIdMap.put(toUsername, callIdHeader.getCallId());
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader =
                headerFactory.createViaHeader(sipinfo.getIp(), sipinfo.getPort(), "udp", "branch1");
        viaHeaders.add(viaHeader);
        ContentTypeHeader contentTypeHeader =
                headerFactory.createContentTypeHeader("Application", "SDP");
        sendMessage(toAddress, toUsername, message, Request.INVITE, callIdHeader, viaHeaders,
                contentTypeHeader, headers, null);
        branchManager.put(viaHeader.getBranch());

    }

    public void sendMessageBYE(String toAddress, String toUsername
    ) throws ParseException, InvalidArgumentException, SipException {
        CallIdHeader callIdHeader = sipProvider.getNewCallId();
        String s = callIdMap.get(toUsername);
        callIdHeader.setCallId(s);
        Dialog dialog = diaLogMap.get(s);
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader =
                headerFactory.createViaHeader(sipinfo.getIp(), sipinfo.getPort(), "udp", "branchbye");
        viaHeaders.add(viaHeader);
        ContentTypeHeader contentTypeHeader =
                headerFactory.createContentTypeHeader("Application", "SDP");
        sendMessage(toAddress, toUsername, null, Request.BYE, callIdHeader, viaHeaders,
                contentTypeHeader, Collections.emptyList(), dialog);
        branchManager.put(viaHeader.getBranch());


    }

    public void sendMesdsageACK(String toAddress, String toUsername, FromHeader from,
                                CallIdHeader callId, List<Header> headers)
            throws ParseException, InvalidArgumentException, SipException {
        CallIdHeader callIdHeader = sipProvider.getNewCallId();
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader =
                headerFactory.createViaHeader(sipinfo.getIp(), sipinfo.getPort(), "udp", "branch1");
        viaHeaders.add(viaHeader);
        ContentTypeHeader contentTypeHeader =
                headerFactory.createContentTypeHeader("Application", "SDP");
        sendMessage(toAddress, toUsername, null, Request.INVITE, callIdHeader, viaHeaders,
                contentTypeHeader, headers, null);
    }

    public void sendMessage(String toAddress, String toUsername, Object message, String method,
                            CallIdHeader callIdHeader, List<ViaHeader> viaHeaders, ContentTypeHeader contentTypeHeader,
                            List<Header> headers, Dialog dialog) throws ParseException, InvalidArgumentException, SipException {
        ToHeader toHeader = getToHeader(toUsername, toAddress, null);

        SipURI requestURI = addressFactory.createSipURI(toUsername, toAddress);
        requestURI.setTransportParam("udp");

        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, method);

        FromHeader fromHeader = getFromHeader();

        // 用于结束会话
        if (dialog != null) {
            toHeader.setTag(dialog.getRemoteTag());
            fromHeader.setTag(dialog.getLocalTag());
            cSeqHeader.setSeqNumber(2L);
        }
        Request request = messageFactory.createRequest(requestURI, method, callIdHeader, cSeqHeader,
                fromHeader, toHeader, viaHeaders, maxForwards);

        request.addHeader(contactHeader);
        for (Header header : headers) {
            request.setHeader(header);
        }
        if (message != null) {
            request.setContent(message, contentTypeHeader);


        }
        sipProvider.sendRequest(request);
    }
}
